GSP-024 Build a Slack Bot with Node.js on Kubernetes

2017 11 3일 금요일

오전 8:52

링크: https://google.qwiklabs.com/focuses/6023

 

오버뷰

1) Botkit toolkit 으로 https://api.slack.com/bot-users

2) Slack bot을 만들자 https://botkit.ai/

3) 만든걸 GCP 에서 돌려보자

 

이제 Slack channel 에서 인터렉티브하게 돌릴 수 있을거다

45ed81def167b732.png

 

배우게 되나?

 

- 슬랙에서 봇을 커스텀하게 생성

- docker에서 Node.js 이미지를 build

- Docker image Google Container Registry (=private 하다) 에 넣어둔다

- 슬랙봇을 GCK (Google Container Engine)에 올리자. GKE = managed Kubernetes service

 

 

Create a Slack Team

 

: https://slack.com/create#email

 

참여한, 봇을 실험할 수 있는 슬랙팀에 가입되어 있어야겠죠?

아니면 하나 만들어버리구요.

 

Get the sample code

 

깃헙에서 가져오면 된다.

 

 

 

- package.json 이 포함된 프로젝트가 있을때에 (node.js, angular 등등)

- npm install 을 실행하면

- package.json 에 설정된 종속 라이브러리 (=dependencies) 를 다운받고 설치해준다

jhstyoungmin-PC (master) 
cat package. j son 
"name" : , 
"version": "I.e.e", 
"description" : 
"A sample Stack Botkit Sot. " 
"main" : 
"kittenbot. j s" , 
"dependencies": { 
"botkit" : 
"e. 1.1" 
" devDependencies " : { 
"standard": " ".1.1" 
"scripts": { 
"test": "standard 
repository" : { 
"type": "glt 
"urt": 
"https : / / github. con/ tabs/ c loud—s tack—bot. git" 
"author" : 
"Google Inc.", 
" license " : 
" Apache—2. e "

 

 

Create a Slack bot user

 

링크: https://api.slack.com/bot-users

bot user

- slack 의 메시지를 들을 수 있고,

- 메시지를 post 할 수 있고,

- 파일을 upload 할 수 있다.

 

간단히 인사를 하는 슬랙봇을 만들어보자.

 

Create a new Slack app

 

앱을 새로 만들자 https://api.slack.com/apps

1) kittenbot 이라고 만들고

2) 봇을 적용할 slack team을 선택하자

 

Add a new bot user to the app

 

1) app configuration page 에서 Bot user를 선택하고

2) Add a bot user 를 클릭

3) @kittenbot 이라고 이름지어주고

4) Always show toe bot as online 을 끌 것

- Realtime Messaging API (RTM) 을 쓸거라서 그럼

- bot user bot 으로부터 연결이 있을때만 online 이 될 거다.

5) Add bot user 클릭

 

 Get the bot user OAuth access token

 

1) app configuration page OAuth & Permissions 선택

- 아래 추가해줘야 한다

시스템 생성 대체 텍스트:
Scopes 
Scopes define the API methods this app is allowed to [삶 
capabilities are available on a workspace it's installed 이1. 
resources like channels or files. 
If your app is submitted to the Slack App Directory, we'll 
scope. After your app is listed in the Directory, it will 이위) 
has approved. 
Select Permission Scopes 
Add permission by scope or API method.. 
OTHER 
Add bot user with the username @kittenbot 
bot

 

- 그러고 나면  install 항목이 enable 되고, 진행하면 된다

시스템 생성 대체 텍스트:
Tokens for Your Workspace 
These tokens were automatically generated when Ⅵ 
use these to authenticate your app. Learn more. 
OAuth Access Token 
xoxp-5025865657-5025865659-266384524964

 

2) Reinstall app 클릭

- app team  reinstall 해주고

- bot user team에 추가해준다

3) Bot user OAuth access token을 복사해둔다

- 요거 보안에 주의해주세요

- git에 넣어두거나 누구 보여주면 안됨

시스템 생성 대체 텍스트:
OAuth Access Token 
xoxp-5025865657-5025865t 
Bot user OAuth Ac뚀55 Token 
xoxb-267219841958-T5YYa.!

 

Run the sample app

 

1) kittenbot.js 파일에 복사해둔 Slack bot token을 넣어준다.

- 코드에서 your-slack-token 이라는 데를 찾아서 넣어준다

시스템 생성 대체 텍스트:
Var Botkit = require( • • ) 
var controller = Botkit. 5 tackbot({debug 
controller 
-spawn({ 
.startRTX(function (err) { 
if (err) { 
n하』 Error(err) 
control ter. hears( 
['he110' 
function 
false}) 
// Edit this tine! 
t10 
• hi ]』 [ • direct message' , 'direct 
(bot, *55예e) { 
bot. reply(message, 
t10 
'Meow.

 

2) node kittenbot.js

3) slack 에서 direct messages 에서 볼 수 있을것이다. 안보이면 찾아내면 된다

- hello 하고 인사해보자 ㅎㅎ

 

Load Slack token from a file

 

코드에 token을 넣어둔채로 docker image를 만들 순 없잖아?

- Kubernetes Secrets 를 쓰면 된다

- 링크( TR;DR): https://kubernetes.io/docs/concepts/configuration/secret/

 

1. slack-token 이라는 파일을 만들자

- .gitignore에 이미 들어있어서 git 을 통해 올라가지도 않는다.

jhstyoungmin-PC (master) 
cat . gitignore 
logs 
pids 
pid 
Directory for instrumented tibs generated by jscoverage/JSCover 
Coverage directory used by toots tike istanbut 
Grunt intermediate storage (http://gruntjs.con/creating—ptugins#storing—task—fites) 
. grunt 
node—aaf configuration 
. tock—a script 
Compiled binary addons (http://nodejs.org/api/addons.htmt) 
• td/Retease 
Dependency directory 
h t tps : / / docs. nwlj s. con/ faq*shou les—fo 
Optional np• cache directory 
Optional REPL history 
. node_ rep t_hi story 
Generated files with project—specific information 
tack—token

 

2. kittenbot.js 파일 수정

var 
var 
var 
Botkit = require('botkit') 
fs = require('fs') 
controller = false}) 
if ( ! process. env. s 
console. tog(' Error: Specify in environment') 
process. exit(l) 
fs. readFite process. env. function (err, data) 
if (err) 
console. tog(' Error: Specify token in file') 
process. exit(l) 
data = String(data) 
data = data. 
con ro er 
. token: data 
, ' // space, 
tab, etc, "g: globat 
. startRTX(function (err) { 
if (err) { 
throw new Error(err) 
control ter. hears( 
'Nello', ' 
function (Sot, message) { 
contro er. 
spacosa ' 
function (bot, message) { 
hi'], ['direct_message', 'direct_mention' , 
Sot. repty(message, 
' company'], ['direct_message' 
Sot. reply (message, 
'mention' 
'direct mention', 'mention' 
'best company! .

1. slack_token_path 존재 여부 확인

- 파일을 읽는다

 

2. token 값을 읽어온걸 정규식으로 다듬는다

/\s/g, '' 에서

\s 는 스페이스, 등등의 공백

/g 는 글로벌하게 찾아서

'' 로 바꿔라 = 없애버려라

 

3. 문답을 하나 더 추가해보았음

 

3. slack-token 파일에 kittenbot.js 에 넣어둔 토큰을 복사해 넣는다. 그리고 실행

 

Create a Docker container image

 

FROM node:5.4 
COPY package.json /src/package .json 
WORKDIR /src 
RUN npm install 
COPY kittenbot.js /src 
CMD ["node" , 
" /src/kittenbot. js" ]

1. node 5.4 버전 이미지를 base로 해서 이미지를 만든다

2. 현재 폴더의 package.json 파일을 base 도커이미지의 /src/package.json 으로 복사

3. WORKDIR 환경변수는 /src 로 설정

4. RUN npm install 하면

- base 도커이미지에

- package.json 에 명시된대로 dependencies 가 설치됨

5. kittenbot.js 파일을 /src 폴더로 복사

5. 실행명령 node /src/kittenbot.js 실행

 

빌드는 그냥 PROJECT_ID를 넣어도 되는데 범용성을 위해 아래와 같이 하는 것 같다

 

 

 

 

 

 

Extra Credit: Create a incoming webhook to Slack

 

도커 빌드되는 동안 다른걸 쫌 더 해볼까?

incoming webhook: https://api.slack.com/incoming-webhooks

- 데이터를 실시간으로 Slack 에게 보내기?

- 이 경우 bot user 처럼 양방향 (two-way) 연결 유지를 고민할 필요 없음

 

Slack Custom Intergrations management console로 간다

- https://my.slack.com/apps/manage/custom-integrations

- Incoming Webhooks >> Add configuration 버튼 클릭

- 메시지를 포스트하고 싶은 Slack Channel 선택

- Add incoming webhooks integration 버튼 클릭

Incoming Webhooks 가 왼쪽 가이드대로 해도 안나오길래 상단 검색

Q incoming 
Incoming WebHooks 
Send data into Slack in real-tme.

 

 

Testing a Docker image locally

 

일단 내 컴터에서 도커로 돌려보기

 

빌드는 되었다

 

 

(원래명령)

docker run -d \ 
-v S/pwdM:/config \ 
gcr.ioL PROJECT_ID -'slack-codelab:vl

 

(실행)

- 윈도우라 pwd 명령이 없음.

- 그냥 e:\git\cloud-slack-bot\start 라고 명시해준 부분 참고

- "-v" 옵션은 도커가 아닌 실제 컴퓨터의 이 부분을 사용하겠다는 이야기임. slack-token 파일에 접근하기 위해서 여기서는 이렇게 사용함

 

 

Pushing a Docker image to Google Container Registry

 

로컬의 docker image를 구글의 Registry에 넣어보자

- 전에 해보니, 아까 build 할때에 project id를 제대로 안적었다면 push 되지 않았었다

 

 

Google Cloud Platform 
Container Registry 
Images 
Build triggers 
Build history 
My Project 
Images 
C REFRESH 
Registry location: gcrjo O 
Name A 
hello-node 
slack-codelab

 

 

Extra Credit: Testing an incoming webhook

 

Google Container Registry push 하는 동안 웹훅 다시보기

- push 되는 중으로 가정하고 cloud shell session을 하나 더 연다

e876cbd7bd3a1f32.png

 

- 나는 그냥 로컬 컴터니깐 cmd 창 하나 새로 열면 됨

 

아까 웹훅 만들었을때 URL을 보자

Webhook URL 
Send wur JSON payloads to this URL. 
Show setup instructions 
Copy URL • Regenerate

 

curl 을 이용해서 HTTP request 를 보내보자

curl -X POST --data-urlencode \ 
payload={"text": "Hello from Cloud Shell. " } ' 
https:/'hooks.slack.com/services/ YOUR/WEBHOOK 'URL

 

S curt —X POST —data—urtencode \ 
> "Helto frwl Cloud Shen. \ 
> https://hooks.stack.co./ser.ices/T050RRFKB/B7TPXATLG/t014•

 

incoming-webhook 
App 7:41 PM 
'-3 Hello from Cloud Shell.

* 잔디 커넥트의 인커밍 웹훅도 재미날듯 하다

 

Create a Kubernetes cluster on Google Container Engine

 

bot 이 잘 동작하는지 모니터링 해줄 녀석이 필요하다.

- 도커가 멈춰도 restart 해주고

- 심지어는, 컴터가 뻑이나도 다른 컴터에서 돌려줄 녀석

= Kubernetes

 

Container Engine Cluster

 

- 구글에서 제공하는 managed Kubernetes cluster

- Contaner Engine Cluster 는 둘로 이루어져 있다.

1) Kubernetes master API server (hosted by Google)

2) a set of worker nodes (= Compute Engine VMs)

 

gcloud container clusters create my-cluster \ 
-num-nodes:2 N 
-zone:us-centrall-f \ 
--machine-type nl-standard-l

 

1) container  cluster를 만들어라. 이름은 my-cluster

2) 노드 = VM = 2

3) 지역은 us-central1-f

4) 컴터 종류는 n1-standard-1

 

만들어는 주는데, 이후 Container Engine Cluster에 접근하려면 kubectl 이 필요하다고 알려줌

nicenook@youngmin-PC: S gcloud container clusters create my—cluster —num—nodes 2 
Accessing a Container Engine cluster requires the kuöernetes cognandline 
client [kuöectl]. To install, run 
S gctoud components instat kubectt 
reating cluster my—cluster.. -done. 
—zone —machine—type 
reated [https://container.googleapis.cæ/vI/projects/potished—zephyr—176321/zones/us—centratI—f/ctusters/my—ctuster] . 
kuöeconfig entry generated for my—cluster. 
RASTER VERSION RASTER IP 
RACHINE TYPE WOE VERSION WOES STATUS 
—cluster 1.7.8—gke. 
35.193.165.209 ill-standard-1 1.7.8-gke.e 2

 

웹콘솔로 노드 = VM 생성 확인

VM instances 
Q 
Compute Engine 
VM instances 
Instance groups 
Instance templates 
Disks 
Snapshots 
Images 
CREATE INSTAM 
Instance •jhs vml• is underutilized. You can save a 
Filter VM instances 
Name A 
e gke-my-cluster-default-pool-ef636a11-mg9w 
e gke-my-cluster-defauIt-pool-ef636a11-nz13

 

CLI로도 확인이 가능하다

 

Create a Deployment

 

먼저 Slack Token을 저장하기 위해 Kubernetes Secret 이란걸 만들자

- 링크: https://goo.gl/321yg4

 

Deploy 를 어떻게 할지를 명시한 yaml 파일 만들기

apiVersion: extensions/vlbetal 
kind: Deployment 
metadata : 
name: slack-codelab 
spec : 
replicas: 1 
strategy : 
type: Recreate 
template : 
metadata : 
labels : 
app: slack-codelab 
spec : 
containers : 
name: master 
Image: gcr. io/PROJECT_ID/s1ack-code1ab 
volumeMounts : 
name: slack-token 
mountPath: /etc/slack-token 
name: slack_token_path 
value: 'etc/ slack-token/ slack-token 
volumes : 
name: slack-token 
secret: 
secretName: slack-token 
# Replace PROJECT_ID 
# with your project ID.

 

드디어 실제로 Deployment

 

"-f" 는 파일명

"--record"는 대략 kubectl 명령기록 저장인가?

—record=fatse: Record current kuöectt cognand in the resource annotation. If set to false, do not record the 
cognand. If set to true, record the cognand. If not set, default to updating the existing annotation value only if one 
already exists.

 

Running 확인

nicewook@youngmin—PC : 
S kuöectt get pods 
s Lack—code tab— 176M3R?5.5 
READY 
1/1 
STATUS 
Running 
RESTARTS 
AGE

 

- 이제 슬랙에서 kittenbot 동작될거다

 

Extra Credit: Update your bot to a new version

 

매끄럽게 버전업 하는건 우리의 로망이다.

 

1) kittenbot.js 파일을 변경한다

2) docker build 하여 image를 생성하고

3) gcloud docker -- push 하여 GCP registry에 넣는다

시스템 생성 대체 텍스트:
Google Cloud Platform 
Contalner ReglStry 
Images 
Build triggers 
Build history 
1• My Project 
수 Images 
C REFRES 
gcr io / polished-zephyr-176321 / slack-codf 
Filter by name or tag 
口 
口 
口 
Name 
[=] 8d370efC&7h2 
[=] beOabbb9c9ad 
Tags

4) yaml 파일을 변경한다

- 사용할 docker image만 바꿔주면 된다

 

5) 적용은 kubectl apply -f slack-codelab-deployment.yaml

- 아래는 실시간으로 기존의 image가 돌아가던 pod 이 종료되고

- 새로운 pod이 돌아가는 상황이다

시스템 생성 대체 텍스트:
. n그〔테MOOR@)℃u ngm1n—PC 
5 汰- lab—1260038255-r喬 1 Z 
5 汰- lab—1260038255-r喬 1 Z 
5 lab-313707310- 3K7 
STATUS 
Termlnatlng 
STATUS 
Termlnatlng 
READY 
READY 
1/1 
kuöectl get 
RESTARTS 
Secti get 
RESTARTS 
Secti get 
90d5 
AGE 
90d5 
AGE 
饑ds 
STATUS 
Runnlng 
RESTARTS AGE

 

시스템 생성 대체 텍스트:
h51 습 
hyunseok 
9:51 AM 
cat 
kittenbot APP 9:51 AM 
Does someone need 콤 kitten delivery? Say YES or NO. 
hyunseok 
9:51 AM 
YES 
kittenbot APP 9:51 시던 
Great! 
HOW many? 
hyunseok 
9:51 AM

 

 

Microsoft OneNote 2016에서 작성